import os

from django.core.management.commands.startapp import Command as StartappCommand

from django_custom_command import settings


class Command(StartappCommand):
    def __init__(self, stdout=None, stderr=None, no_color=False, force_color=False):
        super(Command, self).__init__(stdout, stderr, no_color, force_color)
        self.base_path = ""
        self.name = ""
        self.app_names = ""
        self.camel_name = ""

    def set_variables(self, **options):
        if len(options["extensions"]) > 1:
            app_names = options["extensions"].pop().split(",")
            setattr(self, "app_names", app_names)

        name = options.get("name")
        setattr(self, "name", name)

        camel_name = self.to_camel_case(name)
        setattr(self, "camel_name", camel_name)

        if options.get("directory"):
            name = os.path.join(options["directory"], name)

        base_path = os.path.join(settings.BASE_DIR, name)
        setattr(self, "base_path", base_path)

    def handle(self, **options):
        self.set_variables(**options)
        super().handle(**options)

        print("自动生成规范性目录结构以及文件")
        # 创建目录
        dirs = ["filters", "services", "views", "serializers", "models"]
        for dir_complex in dirs:

            dir_path = os.path.join(self.base_path, dir_complex)
            os.mkdir(dir_path)

            # 每个目录底下都需要创建 __init__.py文件
            filepath = os.path.join(dir_path, "__init__.py")
            with open(filepath, "w") as f:
                f.write("# -*- coding: utf-8 -*-")

            # 每个目录下都需要创建app的对应文件，例如:views目录下,app1_view.py
            method_suffix = dir_complex.rstrip("s")
            file_suffix = method_suffix + ".py"
            try:
                if self.app_names:
                    getattr(self, f"create_template_of_{method_suffix}")(file_suffix, dir_path, self.app_names)
            except Exception as e:
                print(f"暂时不支持【{dir_complex}】这个目录下生成文件，详情：{e}")

        # 创建文件
        self.create_base_file()
        files = ["constant.py", "utils.py", "urls.py", "tasks.py"]
        for _file in files:
            file_path = os.path.join(os.path.join(settings.BASE_DIR, self.name), _file)
            with open(file_path, "w") as f:
                f.write("# -*- coding: utf-8 -*-")
        # 删除文件
        self.delete_base_file()

    def delete_base_file(self):
        files = ["models.py", "views.py"]
        for f in files:
            os.remove(os.path.join(self.base_path, f))

    def create_base_file(self):
        files = ["constant.py", "utils.py", "urls.py", "tasks.py"]
        for _file in files:
            file_path = os.path.join(self.base_path, _file)
            with open(file_path, "w") as f:
                f.write("# -*- coding: utf-8 -*-")

    def create_template_of_filter(self, file_suffix, dir_path, app_names):
        content = """
from {name}.models.{app_name}_model import {camel_app_name}
from django_filters.rest_framework.filterset import FilterSet


class {camel_app_name}FilterSet(FilterSet):
    class Meta:
        model = {camel_app_name}
        fields = "__all__"
"""
        self.create(file_suffix, dir_path, app_names, content)

    def create_template_of_view(self, file_suffix, dir_path, app_names):
        content = """
from {name}.filters.{app_name}_filter import {camel_app_name}FilterSet
from {name}.models.{app_name}_model import {camel_app_name}
from {name}.serializers.{app_name}_serializer import (
    {camel_app_name}Serializer,
    {camel_app_name}CreateSerializer,
    {camel_app_name}ListSerializer,
    {camel_app_name}RetrieveSerializer,
    {camel_app_name}UpdateSerializer,
    {camel_app_name}PartialUpdateSerializer
)
from common.drf.viewsets import ModelViewSet


class {camel_app_name}ViewSet(ModelViewSet):
    queryset = {camel_app_name}.objects.all()
    serializer_class = {camel_app_name}Serializer
    filter_class = {camel_app_name}FilterSet
    search_fields = ()
    ordering_fields = ("created_time", "updated_time")

    def get_serializer_class(self):
        if self.action == "create":
            return {camel_app_name}CreateSerializer
        if self.action == "list":
            return {camel_app_name}ListSerializer
        if self.action == "retrieve":
            return {camel_app_name}RetrieveSerializer
        if self.action == "update":
            return {camel_app_name}UpdateSerializer
        if self.action == "partial_update":
            return {camel_app_name}PartialUpdateSerializer
        return super({camel_app_name}ViewSet, self).get_serializer_class()
"""
        self.create(file_suffix, dir_path, app_names, content)

    def create_template_of_serializer(self, file_suffix, dir_path, app_names):
        content = """
from rest_framework import serializers

from {name}.models.{app_name}_model import {camel_app_name}
from common.drf.serializers import DynamicFieldsMixin


class {camel_app_name}Serializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = {camel_app_name}
        fields = "__all__"


class {camel_app_name}CreateSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = {camel_app_name}
        fields = "__all__"


class {camel_app_name}ListSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = {camel_app_name}
        fields = "__all__"


class {camel_app_name}UpdateSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = {camel_app_name}
        fields = "__all__"


class {camel_app_name}PartialUpdateSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = {camel_app_name}
        fields = "__all__"


class {camel_app_name}RetrieveSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = {camel_app_name}
        fields = "__all__"

"""
        self.create(file_suffix, dir_path, app_names, content)

    def create_template_of_service(self, file_suffix, dir_path, app_names):
        content = """
class {camel_app_name}Service:
    pass
"""
        self.create(file_suffix, dir_path, app_names, content)

    def create_template_of_model(self, file_suffix, dir_path, app_names):
        content = """
from {name}.constant import table_prefix  # 设置你的表前缀
from common.common_model import Model


class {camel_app_name}(Model):
    class Meta:
        db_table = table_prefix + "{app_name}"
        verbose_name = "【填写你的显示名】"
        verbose_name_plural = verbose_name

    def __str__(self):
        return ""
"""
        self.create(file_suffix, dir_path, app_names, content)

    def create(self, file_suffix, dir_path, app_names, content):
        for app_name in app_names:
            camel_app_name = self.to_camel_case(app_name)
            content = content.format(name=self.name, camel_app_name=camel_app_name, app_name=app_name)
            path = os.path.join(dir_path, f"{app_name}_{file_suffix}")
            self.to_write(path, content)

    @staticmethod
    def to_camel_case(s):
        # 下划线转驼峰
        # abc_def -> AbcDef
        parts = s.split("_")
        return "".join(word.capitalize() for word in parts)

    @staticmethod
    def to_write(path, content):
        with open(path, "w", encoding="utf-8") as f:
            f.write(content)
